package com.mall.web.controller.system;

import com.mall.common.annotation.Log;
import com.mall.common.constant.UserConstants;
import com.mall.common.core.controller.BaseController;
import com.mall.common.core.domain.AjaxResult;
import com.mall.common.core.page.TableDataInfo;
import com.mall.common.enums.BusinessType;
import com.mall.common.utils.poi.ExcelUtil;
import com.mall.framework.shiro.service.SysPasswordService;
import com.mall.framework.util.ShiroUtils;
import com.mall.system.domain.entity.SysUser;
import com.mall.system.domain.entity.SysUserRole;
import com.mall.system.service.*;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * 用户信息
 * Created by zhonglin on 2020/4/8.
 */
@Controller
@RequestMapping("/system/user")
public class SysUserController
    extends BaseController {

  private String prefix = "system/user";

  @Autowired
  private SysUserService userService;

  @Autowired
  private SysRoleService roleService;

  @Autowired
  private SysPostService postService;

  @Autowired
  private SysPasswordService passwordService;

  @RequiresPermissions("system:user:view")
  @GetMapping()
  public String user() {

    return prefix + "/user";
  }

  @RequiresPermissions("system:user:list")
  @PostMapping("/list")
  @ResponseBody
  public TableDataInfo list(SysUser user) {

    startPage();
    List<SysUser> list = userService.selectUserList(user);
    return getDataTable(list);
  }

  @Log(title = "用户管理", businessType = BusinessType.EXPORT)
  @RequiresPermissions("system:user:export")
  @PostMapping("/export")
  @ResponseBody
  public AjaxResult export(SysUser user) {

    List<SysUser>      list = userService.selectUserList(user);
    ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
    return util.exportExcel(list, "用户数据");
  }

  @Log(title = "用户管理", businessType = BusinessType.IMPORT)
  @RequiresPermissions("system:user:import")
  @PostMapping("/importData")
  @ResponseBody
  public AjaxResult importData(MultipartFile file,
                               boolean updateSupport)
      throws Exception {

    ExcelUtil<SysUser> util     = new ExcelUtil<SysUser>(SysUser.class);
    List<SysUser>      userList = util.importExcel(file.getInputStream());
    String operName = ShiroUtils.getSysUser()
                                .getLoginName();
    String message = userService.importUser(userList, updateSupport, operName);
    return AjaxResult.success(message);
  }

  @RequiresPermissions("system:user:view")
  @GetMapping("/importTemplate")
  @ResponseBody
  public AjaxResult importTemplate() {

    ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
    return util.importTemplateExcel("用户数据");
  }

  /**
   * 新增用户
   */
  @GetMapping("/add")
  public String add(ModelMap mmap) {

    mmap.put("roles", roleService.selectRoleAll());
    mmap.put("posts", postService.selectPostAll());
    return prefix + "/add";
  }

  /**
   * 新增保存用户
   */
  @RequiresPermissions("system:user:add")
  @Log(title = "用户管理", businessType = BusinessType.INSERT)
  @PostMapping("/add")
  @ResponseBody
  public AjaxResult addSave(@Validated SysUser user) {

    if (UserConstants.USER_NAME_NOT_UNIQUE.equals(userService.checkLoginNameUnique(user.getLoginName()))) {
      return error("新增用户'" + user.getLoginName() + "'失败，登录账号已存在");
    } else if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
      return error("新增用户'" + user.getLoginName() + "'失败，手机号码已存在");
    } else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
      return error("新增用户'" + user.getLoginName() + "'失败，邮箱账号已存在");
    }
    user.setSalt(ShiroUtils.randomSalt());
    user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
    user.setCreateBy(ShiroUtils.getLoginName());
    return toAjax(userService.insertUser(user));
  }

  /**
   * 修改用户
   */
  @GetMapping("/edit/{userId}")
  public String edit(@PathVariable("userId") Long userId,
                     ModelMap mmap) {

    mmap.put("user", userService.selectUserById(userId));
    mmap.put("roles", roleService.selectRolesByUserId(userId));
    mmap.put("posts", postService.selectPostsByUserId(userId));
    return prefix + "/edit";
  }

  /**
   * 修改保存用户
   */
  @RequiresPermissions("system:user:edit")
  @Log(title = "用户管理", businessType = BusinessType.UPDATE)
  @PostMapping("/edit")
  @ResponseBody
  public AjaxResult editSave(@Validated SysUser user) {

    userService.checkUserAllowed(user);
    if (UserConstants.USER_PHONE_NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
      return error("修改用户'" + user.getLoginName() + "'失败，手机号码已存在");
    } else if (UserConstants.USER_EMAIL_NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
      return error("修改用户'" + user.getLoginName() + "'失败，邮箱账号已存在");
    }
    user.setUpdateBy(ShiroUtils.getLoginName());
    return toAjax(userService.updateUser(user));
  }

  @RequiresPermissions("system:user:resetPwd")
  @Log(title = "重置密码", businessType = BusinessType.UPDATE)
  @GetMapping("/resetPwd/{userId}")
  public String resetPwd(@PathVariable("userId") Long userId,
                         ModelMap mmap) {

    mmap.put("user", userService.selectUserById(userId));
    return prefix + "/resetPwd";
  }

  @RequiresPermissions("system:user:resetPwd")
  @Log(title = "重置密码", businessType = BusinessType.UPDATE)
  @PostMapping("/resetPwd")
  @ResponseBody
  public AjaxResult resetPwdSave(SysUser user) {

    userService.checkUserAllowed(user);
    user.setSalt(ShiroUtils.randomSalt());
    user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
    if (userService.resetUserPwd(user) > 0) {
      if (ShiroUtils.getUserId() == user.getUserId()) {
        ShiroUtils.setSysUser(userService.selectUserById(user.getUserId()));
      }
      return success();
    }
    return error();
  }

  /**
   * 进入授权角色页
   */
  @GetMapping("/authRole/{userId}")
  public String authRole(@PathVariable("userId") Long userId,
                         ModelMap mmap) {

    SysUser user = userService.selectUserById(userId);
    // 获取用户所属的角色列表
    List<SysUserRole> userRoles = userService.selectUserRoleByUserId(userId);
    mmap.put("user", user);
    mmap.put("userRoles", userRoles);
    return prefix + "/authRole";
  }

  /**
   * 用户授权角色
   */
  @RequiresPermissions("system:user:add")
  @Log(title = "用户管理", businessType = BusinessType.GRANT)
  @PostMapping("/authRole/insertAuthRole")
  @ResponseBody
  public AjaxResult insertAuthRole(Long userId,
                                   Long[] roleIds) {

    userService.insertUserAuth(userId, roleIds);
    return success();
  }

  @RequiresPermissions("system:user:remove")
  @Log(title = "用户管理", businessType = BusinessType.DELETE)
  @PostMapping("/remove")
  @ResponseBody
  public AjaxResult remove(String ids) {

    try {
      return toAjax(userService.deleteUserByIds(ids));
    } catch (Exception e) {
      return error(e.getMessage());
    }
  }

  /**
   * 校验用户名
   */
  @PostMapping("/checkLoginNameUnique")
  @ResponseBody
  public String checkLoginNameUnique(SysUser user) {

    return userService.checkLoginNameUnique(user.getLoginName());
  }

  /**
   * 校验手机号码
   */
  @PostMapping("/checkPhoneUnique")
  @ResponseBody
  public String checkPhoneUnique(SysUser user) {

    return userService.checkPhoneUnique(user);
  }

  /**
   * 校验email邮箱
   */
  @PostMapping("/checkEmailUnique")
  @ResponseBody
  public String checkEmailUnique(SysUser user) {

    return userService.checkEmailUnique(user);
  }

  /**
   * 用户状态修改
   */
  @Log(title = "用户管理", businessType = BusinessType.UPDATE)
  @RequiresPermissions("system:user:edit")
  @PostMapping("/changeStatus")
  @ResponseBody
  public AjaxResult changeStatus(SysUser user) {

    userService.checkUserAllowed(user);
    return toAjax(userService.changeStatus(user));
  }

}